use std::process::Command;

fn main() {
    let include_path = ["protos"];

    tonic_build::configure()
        .out_dir("src/pb")
        //.protoc_arg("--experimental_allow_proto3_optional")
        .type_attribute("reservation.Status", "#[derive(sqlx::Type)]") // TODO:
        .type_attribute(
            "reservation.QueryRequest",
            "#[derive(derive_builder::Builder)]",
        )
        .with_field_attribute(
            "reservation.QueryRequest",
            &[
                "resource_id",
                "user_id",
                "status",
                "page",
                "page_size",
                "desc",
            ],
            "#[builder(setter(into), default)]",
        )
        //#[builder(default = "42")]
        .with_field_attribute(
            "reservation.QueryRequest",
            &["start", "end"],
            "#[builder(setter(into, strip_option))]",
        )
        .compile_protos(&["protos/reservation.proto"], &include_path)
        .unwrap();

    Command::new("cargo")
        .args(["fmt", "--", "src"])
        .output()
        .unwrap();

    println!("cargo:rerun-if-changed=protos/reservation.proto");
}

trait AttributeExt {
    #[allow(dead_code)]
    fn with_type_attribute(self, path: &[&str], attr: &str) -> Self;
    fn with_field_attribute(self, path: &str, field: &[&str], attr: &str) -> Self;
}

impl AttributeExt for tonic_build::Builder {
    fn with_type_attribute(self, path: &[&str], attr: &str) -> Self {
        path.iter()
            .fold(self, |acc, path| acc.type_attribute(path, attr))
    }

    fn with_field_attribute(self, path: &str, field: &[&str], attr: &str) -> Self {
        field.iter().fold(self, |acc, field| {
            acc.field_attribute(format!("{}.{}", path, field), attr)
        })
    }
}
